/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is Forte for Java, Community Edition. The Initial * Developer of the Original Code is Sun Microsystems, Inc. Portions * Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved. */ package org.netbeans.modules.debugger.jpda; import com.sun.jdi.event.*; import com.sun.jdi.request.*; import com.sun.jdi.*; import java.util.HashMap; import java.util.List; import java.util.Iterator; import org.netbeans.modules.debugger.jpda.util.Executor; import org.netbeans.modules.debugger.jpda.util.Operator; /** * Manages thread hierarchy. Listen on Operator for creating new threads and removing old ones. * * Synchronization: * finish & create hierarchy are synchronized * addThread & removeThread are called from one thread... * * @author Jan Jancura * @version 0.23, May 26, 1998 */ class ThreadManager implements Executor { // private EventRequestManager requestManager; // stores ThreadReference & ThreadGroupReference => JPDAThread & JPDAThreadGroup private HashMap referenceToThread; private JPDADebugger debugger; /** * Creates ThreadManager. It adds Thread requests to given requestManager, and * creates default hierarchy of threads with given root thread group. * Debugger should be suspended when this method is called. */ ThreadManager ( JPDADebugger debugger ) { referenceToThread = new HashMap (); this.debugger = debugger; createHierarchy (debugger.virtualMachine.topLevelThreadGroups ()); ThreadStartRequest req1 = debugger.requestManager.createThreadStartRequest (); req1.setSuspendPolicy (EventRequest.SUSPEND_ALL); debugger.operator.register (req1, this); req1.enable (); ThreadDeathRequest req3 = debugger.requestManager.createThreadDeathRequest (); req3.setSuspendPolicy (EventRequest.SUSPEND_ALL); debugger.operator.register (req3, this); req3.enable (); } // interface Executor ..................................................................... /** * Executes thread start and thread death events. */ public void exec (com.sun.jdi.event.Event event) { if (event instanceof ThreadStartEvent) { try { addThread (((ThreadStartEvent) event).thread ()); } catch (ObjectCollectedException e) { // thread add is off-line } catch (VMDisconnectedException e) { // thread add is off-line } catch (Exception e) { e.printStackTrace (); //some other problem? [PENDING] } debugger.operator.resume (); return; } try { removeThread (((ThreadDeathEvent) event).thread ()); } catch (ObjectCollectedException e) { // thread remove is off-line } catch (VMDisconnectedException e) { // thread add is off-line } catch (Exception e) { e.printStackTrace (); //some other problem? [PENDING] } debugger.operator.resume (); } // main methods ........................................................................ /** * Removes al threads and thread groups. */ public synchronized void finish () { Iterator i = referenceToThread.values ().iterator (); Object ttg; while (i.hasNext ()) if ((ttg = i.next ()) instanceof JPDAThreadGroup) ((JPDAThreadGroup) ttg).removeAllD (); debugger.threadGroup.removeAllD (); } /** * Create hierarchy for given list of thread groups. * Creates top level thread groups, and calls createHierarchy for all of them. */ synchronized void createHierarchy (List l) { int i, k = l.size (); for (i = 0; i < k; i++) { ThreadGroupReference tgr = (ThreadGroupReference) l.get (i); JPDAThreadGroup ttg = createThreadGroup (tgr, debugger.threadGroup); createHierarchy (tgr, ttg); } } /** * Returns JPDAThread for given ThreadReference. */ JPDAThread findThread (ThreadReference tr) { return (JPDAThread) referenceToThread.get (tr); } /** * Returns JPDAThread for given ThreadReference. */ JPDAThread getThread (ThreadReference tr) { JPDAThread t = findThread (tr); if (t != null) return t; return addThread (tr); } /** * Returns JPDAThreadGroup for given ThreadReferenceGroup. */ JPDAThreadGroup getThreadGroup (ThreadGroupReference tgr) { return (JPDAThreadGroup) referenceToThread.get (tgr); } // other methods ........................................................................ /** * Create hierarchy for given threadGroup and its JPDAThreadGroup. */ private void createHierarchy (ThreadGroupReference tgr, JPDAThreadGroup ttg) { List l = tgr.threadGroups (); int i, k = l.size (); for (i = 0; i < k; i++) { ThreadGroupReference ntgr = (ThreadGroupReference) l.get (i); createHierarchy (ntgr, createThreadGroup (ntgr, ttg)); } l = tgr.threads (); k = l.size (); for (i = 0; i < k; i++) createThread ((ThreadReference) l.get (i), ttg); } /** * Adds new thread to the thread hierarchy. */ private JPDAThread addThread (ThreadReference tr) { JPDAThread tt = (JPDAThread) referenceToThread.get (tr); if (tt != null) return tt; //removeThread (tr); try { return createThread (tr, createThreadGroup (tr.threadGroup ())); } catch (NullPointerException e) { //S ystem.out.println("!!! ThreadManager.thread null " + tr.name ()); // NOI18N return null; } } /** * Removes existing thread from the thread hierarchy. */ private JPDAThread removeThread (ThreadReference tr) { JPDAThreadGroup ttg = (JPDAThreadGroup) referenceToThread.get (tr.threadGroup ()); if (ttg == null) return null; JPDAThread tt = (JPDAThread) referenceToThread.remove (tr); ttg.removeThread (tt); return tt; } /** * Finds or creates JPDAThreadGroup for given ThreadGroupReference. Creates whole * hierarchy of parents of this thread. * * @returns JPDAThreadGroup for given ThreadGroupReference. (Not null!). */ private JPDAThreadGroup createThreadGroup (ThreadGroupReference tgr) { JPDAThreadGroup ttg = (JPDAThreadGroup) referenceToThread.get (tgr); if (ttg != null) return ttg; ThreadGroupReference ptgr = tgr.parent (); // if (ptgr == null) return debugger.threadGroup; JPDAThreadGroup pttg = createThreadGroup (ptgr); return createThreadGroup (tgr, pttg); } /** * Create JPDAThreadGroup for given ThreadGroupReference and parent thread group. */ private JPDAThreadGroup createThreadGroup (ThreadGroupReference tgr, JPDAThreadGroup pttg) { JPDAThreadGroup ttg = new JPDAThreadGroup (pttg, tgr); referenceToThread.put (tgr, ttg); pttg.addThreadGroup (ttg); return ttg; } /** * Create JPDAThread for given ThreadReference and parent thread group. */ private JPDAThread createThread (ThreadReference tr, JPDAThreadGroup pttg) { JPDAThread tt = new JPDAThread (debugger, pttg, tr); referenceToThread.put (tr, tt); pttg.addThread (tt); return tt; } } /* * Log * 7 Gandalf 1.6 1/14/00 Daniel Prusa NOI18N * 6 Gandalf 1.5 11/9/99 Jan Jancura Synchronize adding of * threads * 5 Gandalf 1.4 10/23/99 Ian Formanek NO SEMANTIC CHANGE - Sun * Microsystems Copyright in File Comment * 4 Gandalf 1.3 9/28/99 Jan Jancura * 3 Gandalf 1.2 9/2/99 Jan Jancura * 2 Gandalf 1.1 8/17/99 Jan Jancura Actions for session added * & Thread group current property * 1 Gandalf 1.0 7/13/99 Jan Jancura * $ */